package com.douqu.game.main.server.netty;


import com.alibaba.fastjson.JSONObject;
import com.bean.core.buffer.ByteBuffer;
import com.bean.core.util.HttpJsonUtils;
import com.douqu.game.core.database.model.GMModel;
import com.douqu.game.core.factory.CodeFactory;
import com.douqu.game.core.factory.ConfigFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.WorldInfoFactory;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.core.util.BufferUtils;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.database.mapper.read.ReadPlayerMapper;
import com.douqu.game.main.msg.GMChannel;
import com.douqu.game.main.server.LoadManager;
import com.douqu.game.main.server.SpringContext;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;


/**
 * Created by bean on 2017/3/9.
 */
public class NettyGMServerHandler extends ChannelInboundHandlerAdapter
{

    private NettyConnection connection;


    /*
      * channelAction
      *
      * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
      *
      */
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        LogUtils.info("Client Connect Success:"+ctx.channel().remoteAddress());

        connection = new NettyConnection(ctx.channel(), DataFactory.currentTime);
    }



    /*
     * channelInactive
     *
     *
     * 当客户端主动断开服务端的 链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     *
     */
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        LogUtils.info("Client Disconnect:" + connection);

        GameServer.getInstance().getWorldManager().delGM(connection);

        connection.destroy();
    }


    /**
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
    {
        if(LoadManager.loading || LoadManager.updating)
        {
            GMChannel.sendError(connection, "服务器正在更新, 请稍候再试!");
            return;
        }

        ByteBuf byteBuf = (ByteBuf) msg;
        try{
            int code = BufferUtils.readShort(byteBuf);

            LogUtils.info("code: " + Integer.toHexString(code) + "-> data length: " + byteBuf.readableBytes());

            if(code == CodeFactory.GM_LOGIN)
            {

                ByteBuffer data = CoreUtils.toByteBuffer(byteBuf);

                String username = data.readUTF();
                String password = data.readUTF();

                LogUtils.info("GM用户登录 -> username:" + username + " password:" + password);

//                GMService gmService = SpringContext.getBean(GMService.class);
                //认证需要返回更新后的列表
                JSONObject resJson = HttpJsonUtils.httpPost(GameServer.getInstance().getAuthServerHost() + "gm/login?username=" + username + "&password=" + password);
                if(resJson == null)
                {
                    GMChannel.sendError(connection, "登录失败,请检查服务器");
                    return;
                }
                if(!resJson.getString("code").equals("0000"))
                {
                    GMChannel.sendError(connection, resJson.getString("message"));
                    return;
                }
                GMModel gmModel = JSONObject.parseObject(resJson.getString("data"), GMModel.class);
//                GMModel gmModel = gmService.findByName(username);
                if(gmModel == null || !gmModel.getPassword().equals(password))
                {
                    GMChannel.sendError(connection, "账号或密码错误!");
                    return;
                }

                if(gmModel.isDel())
                {
                    GMChannel.sendError(connection, "你的账户已被禁用,请联系超级GM");
                    return;
                }

                 //判断是否否已经登录，顶出先前的账号
                GameServer.getInstance().getWorldManager().checkLoginOther(username);

                connection.setObject(gmModel);
                GameServer.getInstance().getWorldManager().addGM(connection);

                ReadPlayerMapper readPlayerMapper = SpringContext.getBean(ReadPlayerMapper.class);

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("playerCount", readPlayerMapper.findAllCount(null));
                jsonObject.put("username", username);

                jsonObject.put("userLevel", gmModel.getType());
                jsonObject.put("version", SpringContext.getVersion().getKey());
                jsonObject.put("lastUpdateConfigTime", LoadManager.lastUpdateTime);
                jsonObject.put("rechargeConfig", DataFactory.getInstance().getDetailDataToJson(DataFactory.RECHARGE_KEY));
                jsonObject.put("propConfig", DataFactory.getInstance().getBaseDataToJson(DataFactory.PROP_KEY));
                jsonObject.put("assetConfig", DataFactory.getInstance().getBaseDataToJson(DataFactory.ASSET_KEY));
                jsonObject.put("cardConfig", DataFactory.getInstance().getBaseDataToJson(DataFactory.CARD_KEY));
                jsonObject.put("maxPlayerLv", ConfigFactory.MAX_PLAYER_LV);


                WorldInfoFactory worldInfo = WorldInfoFactory.getInstance();
                if(worldInfo.getServerId() > 0)
                {
                    JSONObject worldInfoObj = new JSONObject();
                    worldInfoObj.put("id", worldInfo.getServerId());
                    worldInfoObj.put("playerIndex", worldInfo.getPlayerIndex());
                    worldInfoObj.put("authServerHost", worldInfo.getAuthServerHost());
                    worldInfoObj.put("battleServerHost", GameServer.getInstance().getServerHost());
                    worldInfoObj.put("configUpdateHost", worldInfo.getConfigUpdateHost());
                    worldInfoObj.put("freeCount", worldInfo.getFreeCount());
                    worldInfoObj.put("crowdCount", worldInfo.getCrowdCount());
                    worldInfoObj.put("fullCount", worldInfo.getFullCount());
                    worldInfoObj.put("createTime", worldInfo.getStartServerTime());
                    //worldInfoObj.put("bonusCount", worldInfo.getBonusCount());
                    jsonObject.put("worldInfo", worldInfoObj);
                }

                jsonObject.put("otherConfig", JSONObject.toJSON(ConfigFactory.gmSetting));

                ByteBuffer out = new ByteBuffer();
                out.writeUTF(jsonObject.toJSONString());

                connection.sendMsg(code, out.getBytes());

            }
            else if(code == CodeFactory.GM_LOGOUT)
            {
                GameServer.getInstance().getWorldManager().delGM(connection);

                Object userInfo = connection.getObject();
                ByteBuffer out = new ByteBuffer();
                if(userInfo != null && userInfo instanceof GMModel)
                {
                    out.writeUTF(((GMModel) userInfo).getUsername());
                }
                connection.sendMsg(code, out.getBytes());

                connection.destroy();
            }
            else
            {
                if(connection.getObject() == null)
                    return;

                if(!(connection.getObject() instanceof GMModel))
                    return;


                GMChannel.messageChannel(code, connection, byteBuf);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            byteBuf.release();
        }


    }




    /*
     * channelReadComplete
     *
     * channel  通道
     * Read     读取
     * Complete 完成
     *
     * 在通道读取完成后会在这个方法里通知，对应可以做刷新操作
     * ctx.flush()
     *
     */
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /*
     * exceptionCaught
     *
     * exception	异常
     * Caught		抓住
     *
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     *
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
    {
        try{
            LogUtils.debug(cause.getLocalizedMessage());
            cause.printStackTrace();
            GameServer.getInstance().getWorldManager().delGM(connection);
            connection.destroy();
        }catch (Exception e){
            e.printStackTrace();
        }
    }





}
